package com.wmyg.antifake.utils;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.wmyg.antifake.enums.PackLevels;

import javax.xml.crypto.Data;
import java.awt.image.BufferedImage;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Random;

public class MaterialCodeUtil {

    private static String UPPER = "QWERTYUIOPASDFGHJKLZXCVBNM";

    private static String LOWER = "qwertyuiopasdfghjklzxcvbnm";

    private static String NUMBER = "0123456789";

    public static final String GTIN_SIGN = "(01)";

    public static final String BATCH_SIGN = "(10)";

    public static final String SERIAL_SIGN = "(21)";

    public static String createGS1Code(String gtin, String batch, String packLevel) {
        while (gtin.length() < 14) {
            StringBuffer sb = new StringBuffer();
            sb.append("0").append(gtin);
            gtin = sb.toString();
        }
        if ("".equals(batch.trim())||null == batch) {
            Random random = new Random();
            StringBuffer sb = new StringBuffer();
            sb.append(randomString(3, UPPER)).append(randomString(3, NUMBER));
            batch = sb.toString();
        }
        StringBuffer serial = new StringBuffer(PackLevels.getLevel(packLevel).getEng());
        serial.append(new SimpleDateFormat("yyMMdd").format(new Date()));
        String time = datetoString();
        serial.append(time);
        serial.append(randomString(9-time.length(), UPPER, NUMBER));
        return "(01)" + gtin + "(10)" + batch + "(21)" + serial.toString();
    }

    public static String createGS1Code2() {
        StringBuffer sb = new StringBuffer();
        String time = datetoString();
        sb.append(time);
        sb.append(randomString(7-time.length(), UPPER, NUMBER));
        return sb.toString();
    }

    private static String randomString(int length, String ... strings) {
        StringBuffer sb = new StringBuffer();
        for (String s:
             strings) {
            sb.append(s);
        }
        StringBuffer result = new StringBuffer();
        for (int i=0; i<length; i++) {
            Random random = new Random();
            result.append(sb.charAt(random.nextInt(sb.length())));
        }
        return result.toString();
    }

    public static BufferedImage createQRPic(String qR, Integer level) {
        BufferedImage image = null;
        int width = 300;
        int height = 300;
        String format = "jpeg";
        HashMap hints = new HashMap();
        hints.put(EncodeHintType.CHARACTER_SET, "ASCII");
        switch (level) {
            case 1:
                hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
                break;
            case 0:
                hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
                break;
            case 3:
                hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q);
                break;
            case 2:
                hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
                break;
            default:
                break;
        }
        hints.put(EncodeHintType.MARGIN, 1);
        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(qR, BarcodeFormat.QR_CODE, width, height, hints);
            image = MatrixToImageWriter.toBufferedImage(bitMatrix);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return image;
    }

    public static BufferedImage createBarcode(String code) {
        BufferedImage image = null;
        int width = 120;
        int height = 80;
        String format = "jpeg";
        HashMap hints = new HashMap();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H);
        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(code, BarcodeFormat.EAN_13, width, height, hints);
            image = MatrixToImageWriter.toBufferedImage(bitMatrix);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return image;
    }

    public static String datetoString() {
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        StringBuffer sb = new StringBuffer();
        StringBuffer result = new StringBuffer();
        sb.append(NUMBER).append(UPPER);
        String array = sb.toString();
        Date date = new Date();
        Long time = date.getTime() - calendar.getTimeInMillis();;
        while (time > 0) {
            Long index = time%36;
            result.append(array.charAt(index.intValue()));
            time = time/36;
        }
        return result.reverse().toString();
    }

    public static String timeToString() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        StringBuffer sb = new StringBuffer();
        StringBuffer result = new StringBuffer();
        sb.append(NUMBER).append(UPPER);
        String array = sb.toString();
        Long time = (new Date()).getTime() - calendar.getTimeInMillis() + 60466176L;
//        System.out.println(time);
        while (time > 0) {
            Long index = time%36;
            result.append(array.charAt(index.intValue()));
            time = time/36;
        }
        return result.reverse().append(nanoToString(2)).toString();
    }

    private static String nanoToString(int length) {
        Long time = System.nanoTime();
        StringBuffer sb = new StringBuffer();
        StringBuffer result = new StringBuffer();
        sb.append(NUMBER).append(UPPER);
        String array = sb.toString();
        for (int i=0;i<length;i++) {
            Long index = time%36;
            result.append(array.charAt(index.intValue()));
            time = time/36;
        }
        return result.reverse().toString();
    }

    public static String createDozenId(Integer i) {
        StringBuffer sb = new StringBuffer();
        StringBuffer result = new StringBuffer();
        sb.append(NUMBER).append(UPPER);
        String array = sb.toString();
        result.append(array.charAt(i%36));
        i = i/36;
        result.append(array.charAt(i%36));
        return result.reverse().toString();
    }

    public static String montageGS1(String gtin, String dateString, String batch, String packLevel, String dozenId, String serial) {
        while (gtin.length() < 14) {
            StringBuffer sb = new StringBuffer();
            sb.append("0").append(gtin);
            gtin = sb.toString();
        }
        StringBuffer result = new StringBuffer();
        return result.append(GTIN_SIGN).append(gtin).append(BATCH_SIGN).append(dateString).append(SERIAL_SIGN)
                .append(batch).append(PackLevels.getLevel(packLevel).getEng()).append(dozenId).append(serial).toString();
    }
}
